import {
  ScriptFactory,
  IControlProvider,
  findChildFormDetails,
} from '@ibiz-template/runtime';
import {
  useUIStore,
  useNamespace,
  useControlController,
} from '@ibiz-template/vue3-util';
import { IDEFormDetail, IDESearchForm } from '@ibiz/model-core';
import {
  h,
  VNode,
  PropType,
  reactive,
  computed,
  renderSlot,
  defineComponent,
  resolveComponent,
} from 'vue';
import { AdvancedSearchFormController } from '../../controller';
import { IModalOptions } from '../../interface';
import './search-form.scss';

export const SearchFormControl = defineComponent({
  name: 'IBizSearchFormControl',
  props: {
    modelData: {
      type: Object as PropType<IDESearchForm>,
      required: true,
    },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    provider: { type: Object as PropType<IControlProvider> },
    isSimple: { type: Boolean, required: false },
    loadDefault: { type: Boolean, default: true },
  },
  setup(props, { slots }) {
    const c = useControlController((...args) => {
      return new AdvancedSearchFormController(...args);
    });

    const ns = useNamespace('search-form');
    const ns2 = useNamespace('search-form-model');
    const { zIndex } = useUIStore();
    const dialogZIndex = zIndex.increment();

    // 处理自定义样式
    const customStyle = computed(() => {
      const tempStyle = {};

      const { width, height } = c.state as IParams;
      if (width) Object.assign(tempStyle, { width });
      if (height) Object.assign(tempStyle, { height });
      return tempStyle;
    });

    // 是否为只有搜索
    const isSearchOnly = computed(() => {
      return c.model.searchButtonStyle === 'SEARCHONLY';
    });

    c.evt.on('onCreated', () => {
      // 表单成员state响应式
      const keys = Object.keys(c.details);
      keys.forEach(key => {
        const detail: IParams = c.details[key];
        detail.state = reactive(detail.state);
      });
    });

    /**
     * 绘制成员的attrs
     * @param {IDEFormDetail} model
     * @return {*}  {IParams}
     */
    const renderAttrs = (model: IDEFormDetail): IParams => {
      const attrs: IParams = {};
      model.controlAttributes?.forEach(item => {
        if (item.attrName && item.attrValue) {
          attrs[item.attrName!] = ScriptFactory.execSingleLine(
            item.attrValue!,
            {
              ...c.getEventArgs(),
              data: c.data,
            },
          );
        }
      });
      return attrs;
    };

    /**
     * 按照类型绘制表单成员
     * @param {IDEFormDetail} detail
     * @return {*}  {(VNode | VNode[] | undefined)}
     */
    const renderByDetailType = (
      detail: IDEFormDetail,
      type?: string,
      isRoot: boolean = false,
    ): VNode | VNode[] | undefined => {
      const { hidden, userTag } = detail as IParams;
      // 根据用户标记判断表单项是否为常驻项，必须要启用高级搜索
      if (
        hidden ||
        (!isRoot &&
          c.model.enableAdvanceSearch &&
          ((type && userTag !== c.permanentKey) ||
            (!type && userTag === c.permanentKey)))
      ) {
        return;
      }
      const detailId = detail.id!;

      // 有插槽走插槽
      if (slots[detailId]) {
        return renderSlot(slots, detailId, {
          model: detail,
          data: c.state.data,
          value: c.state.data[detailId],
        });
      }

      // 子插槽
      const childSlots: IData = {};
      // 表单项如果有编辑器插槽的时候，调用插槽绘制表单项的默认插槽。
      if (detail.detailType === 'FORMITEM' && slots[`${detailId}_editor`]) {
        childSlots.default = (...args: IData[]): VNode[] => {
          return slots[`${detailId}_editor`]!(...args);
        };
      }
      const childDetails = findChildFormDetails(detail);
      if (childDetails.length) {
        // 容器成员绘制子成员
        childSlots.default = (): (VNode[] | VNode | undefined)[] =>
          childDetails.map(child => {
            return renderByDetailType(child, type);
          });
      }

      // 根据适配器绘制表单成员
      const provider = c.providers[detailId];
      if (!provider) {
        return (
          <div>
            {ibiz.i18n.t('control.form.noSupportDetailType', {
              detailType: detail.detailType,
            })}
          </div>
        );
      }
      const component = resolveComponent(provider.component) as string;
      return h(
        component,
        {
          modelData: detail,
          controller: c.details[detailId],
          key: detail.id,
          attrs: renderAttrs(detail),
        },
        childSlots,
      );
    };

    const renderContent = (): JSX.Element => {
      return (
        <div class={[ns2.e('content')]}>
          <div class={[ns2.e('header')]}>
            <span>高级搜索</span>
          </div>
          <div class={[ns2.e('form')]}>
            <iBizFormPage modelData={c.model} controller={c}>
              {c.model.deformPages?.map(page => {
                return renderByDetailType(page, '', true);
              })}
            </iBizFormPage>
          </div>
          <div class={[ns2.e('btn-content')]}>
            <el-button type='primary' onClick={() => c.search()}>
              {ibiz.i18n.t('app.search')}
            </el-button>
            <el-button type='primary' onClick={() => c.reset()}>
              {ibiz.i18n.t('app.reset')}
            </el-button>
          </div>
        </div>
      );
    };

    const onOpenModel = async (): Promise<void> => {
      const { width, height } = c.state as IParams;
      const modal = ibiz.overlay.createModal(renderContent, {}, {
        width,
        height,
        closeOnClickModal: false,
        dragBorder: false,
        draggable: true,
        draggableClass: `.${ns2.e('header')}`,
        modalClass: `${ns2.e('overlay')} ${ns2.em(
          'overlay',
          c.model.searchButtonStyle?.toLocaleLowerCase(),
        )}`,
        customClass: `${ns2.b()}`,
      } as IModalOptions);
      modal.present();
    };

    return {
      c,
      ns,
      customStyle,
      dialogZIndex,
      isSearchOnly,
      onOpenModel,
      renderByDetailType,
    };
  },

  render() {
    const { state } = this.c;
    if (!state.isCreated) {
      return;
    }

    return (
      <div
        class={[this.ns.b()]}
        onKeyup={(e: KeyboardEvent) => this.c.onKeyUp(e)}
      >
        <div class={[this.ns.e('form')]}>
          <iBizFormPage modelData={this.c.model} controller={this.c}>
            {this.c.model.deformPages?.map(page => {
              return this.renderByDetailType(page, 'default', true);
            })}
          </iBizFormPage>
        </div>
        <div class={[this.ns.e('btn-content')]}>
          <el-button type='primary' onClick={() => this.c.search()}>
            {ibiz.i18n.t('app.search')}
          </el-button>
          {!this.isSearchOnly ? (
            <el-button type='primary' onClick={() => this.c.reset()}>
              {ibiz.i18n.t('app.reset')}
            </el-button>
          ) : (
            ''
          )}
          {this.c.model.enableAdvanceSearch ? (
            <el-button type='primary' onClick={this.onOpenModel}>
              高级搜索
            </el-button>
          ) : null}
        </div>
      </div>
    );
  },
});
